﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;

namespace Kokomo.Mirror.PeFormat.Symbols
{
	public class ComWrapper<T>
		where T : class
	{
		public ComWrapper(T comObject)
		{
			if (comObject == null) throw new ArgumentNullException("comObject");

			// Maintain a reference to the original wrapper to keeep the object alive
			this._comObject = comObject;

			this._pUnk = Marshal.GetIUnknownForObject(comObject);
			this._wrapper = comObject;
			this._threadID = Thread.CurrentThread.ManagedThreadId;
		}

		// For reference tracking only
		private T _comObject;

		private IntPtr _pUnk;

		private T _wrapper;
		private int _threadID;

		public T Object
		{
			get
			{
				lock (this)
				{
					Thread.BeginThreadAffinity();

					// TODO: Should be OS thread ID, but close enough
					int threadID = Thread.CurrentThread.ManagedThreadId;
					if (this._threadID != threadID)
					{
						this._wrapper = (T)Marshal.GetUniqueObjectForIUnknown(this._pUnk);
						this._threadID = threadID;
					}
					Thread.EndThreadAffinity();
				}

				return this._wrapper;
			}
		}
	}
}
